<?php defined('SYSPATH') OR die('No direct access allowed.');

abstract class Core_GeraCodigo implements Constants {

	const D = "[0-9]";
	const L = "[A-Za-z]";
	const A = "[A-Za-z0-9]";
	const OP = "\+|\-|\*|/";
	const Q = ".";
	const ASS= "'";
	const ASD = "\"";
	const C = "[(!)(=)(>)(<)]";
	const EB = "[\ \	\r]";
	const NL = "[\
	]";
	
	
    /**
     * [terminais]
     * @var Object
     */
	protected $tokens = array('(',')',',','.','IDENTIFICADOR','STRING','COMPARACAO','INTEIRO','REAL','SELECAO','PROJECAO','CARTESIANO','JUNCAO','UNIAO','AND','OR','NOT');

	/**
	 * [Não Terminais]
	 * @var unknown_type
	 */
	protected $naoterminais = array('<COMANDO>','<SELECAO>','<PROJECAO>','<PROJECAO1>','<CARTESIANO>','<CONJUNTO>','<CONJUNTO1>','<CAMPOS>','<CAMPOS1>','<PREDICADO>','<PREDICADO1>','<PREDICADO2>','<PREDICADO3>','<CRITERIO>','<CRITERIO1>','<TABELA>','<TABELA1>','<ELEMENTO_I>','<ELEMENTO_S>','<ELEMENTO_N>','<ELEMENTO_L>');
	/**
	 * Tabela de analize sintatica.
	 * @var Matriz[NT][T] T-Terminal NT-NãoTerminal
	 */
	protected $tabela = array(//	TERMIAIS    	 $,			 (,			 ),			 .,			 ,,			 IDENTIFICADOR,			 STRING,		 COMPARACAO,		 INTEIRO,		 REAL,			 SELECAO,		 PROJECAO,			 CARTESIANO,		 JUNCAO,		 UNIAO,			 AND,		 OR
							'<COMANDO>'		=>array('$'=>'',	'('=>'',	')'=>'',	'.'=>'',	','=>'',	'IDENTIFICADOR'=>'2',	'STRING'=>'',	'COMPARACAO'=>'',	'INTEIRO'=>'',	'REAL'=>'',		'SELECAO'=>'0',	'PROJECAO'=>'1',	'CARTESIANO'=>'',	'JUNCAO'=>'',	'UNIAO'=>'',	'AND'=>'',	'OR'=>'',	'NOT'=>''),
							'<SELECAO>'		=>array('$'=>'',	'('=>'',	')'=>'',	'.'=>'',	','=>'',	'IDENTIFICADOR'=>'',	'STRING'=>'',	'COMPARACAO'=>'',	'INTEIRO'=>'',	'REAL'=>'',		'SELECAO'=>'6',	'PROJECAO'=>'',		'CARTESIANO'=>'',	'JUNCAO'=>'',	'UNIAO'=>'',	'AND'=>'',	'OR'=>'',	'NOT'=>''),
							'<PROJECAO>'	=>array('$'=>'',	'('=>'',	')'=>'',	'.'=>'',	','=>'',	'IDENTIFICADOR'=>'',	'STRING'=>'',	'COMPARACAO'=>'',	'INTEIRO'=>'',	'REAL'=>'',		'SELECAO'=>'',	'PROJECAO'=>'3',	'CARTESIANO'=>'',	'JUNCAO'=>'',	'UNIAO'=>'',	'AND'=>'',	'OR'=>'',	'NOT'=>''),
							'<PROJECAO1>'	=>array('$'=>'',	'('=>'',	')'=>'',	'.'=>'',	','=>'',	'IDENTIFICADOR'=>'4',	'STRING'=>'',	'COMPARACAO'=>'',	'INTEIRO'=>'',	'REAL'=>'',		'SELECAO'=>'5',	'PROJECAO'=>'',		'CARTESIANO'=>'',	'JUNCAO'=>'',	'UNIAO'=>'',	'AND'=>'',	'OR'=>'',	'NOT'=>''),
							'<CARTESIANO>'	=>array('$'=>'',	'('=>'',	')'=>'',	'.'=>'',	','=>'',	'IDENTIFICADOR'=>'',	'STRING'=>'',	'COMPARACAO'=>'',	'INTEIRO'=>'',	'REAL'=>'',		'SELECAO'=>'',	'PROJECAO'=>'',		'CARTESIANO'=>'',	'JUNCAO'=>'',	'UNIAO'=>'',	'AND'=>'',	'OR'=>'',	'NOT'=>''),
							'<CONJUNTO>'	=>array('$'=>'',	'('=>'',	')'=>'',	'.'=>'',	','=>'',	'IDENTIFICADOR'=>'7',	'STRING'=>'',	'COMPARACAO'=>'',	'INTEIRO'=>'',	'REAL'=>'',		'SELECAO'=>'',	'PROJECAO'=>'',		'CARTESIANO'=>'',	'JUNCAO'=>'',	'UNIAO'=>'',	'AND'=>'',	'OR'=>'',	'NOT'=>''),
							'<CONJUNTO1>'	=>array('$'=>'11',	'('=>'',	')'=>'11',	'.'=>'',	','=>'',	'IDENTIFICADOR'=>'',	'STRING'=>'',	'COMPARACAO'=>'',	'INTEIRO'=>'',	'REAL'=>'',		'SELECAO'=>'',	'PROJECAO'=>'',		'CARTESIANO'=>'10',	'JUNCAO'=>'8',	'UNIAO'=>'9',	'AND'=>'',	'OR'=>'',	'NOT'=>''),
							'<CAMPOS>'		=>array('$'=>'',	'('=>'',	')'=>'',	'.'=>'',	','=>'',	'IDENTIFICADOR'=>'12',	'STRING'=>'',	'COMPARACAO'=>'',	'INTEIRO'=>'',	'REAL'=>'',		'SELECAO'=>'',	'PROJECAO'=>'',		'CARTESIANO'=>'',	'JUNCAO'=>'',	'UNIAO'=>'',	'AND'=>'',	'OR'=>'',	'NOT'=>''),
							'<CAMPOS1>'		=>array('$'=>'',	'('=>'14',	')'=>'',	'.'=>'',	','=>'13',	'IDENTIFICADOR'=>'',	'STRING'=>'',	'COMPARACAO'=>'',	'INTEIRO'=>'',	'REAL'=>'',		'SELECAO'=>'',	'PROJECAO'=>'',		'CARTESIANO'=>'',	'JUNCAO'=>'',	'UNIAO'=>'',	'AND'=>'',	'OR'=>'',	'NOT'=>''),
							'<PREDICADO>'	=>array('$'=>'',	'('=>'15',	')'=>'',	'.'=>'',	','=>'',	'IDENTIFICADOR'=>'15',	'STRING'=>'',	'COMPARACAO'=>'',	'INTEIRO'=>'',	'REAL'=>'',		'SELECAO'=>'',	'PROJECAO'=>'',		'CARTESIANO'=>'',	'JUNCAO'=>'',	'UNIAO'=>'',	'AND'=>'',	'OR'=>'',	'NOT'=>''),
							'<PREDICADO1>'	=>array('$'=>'',	'('=>'16',	')'=>'',	'.'=>'',	','=>'',	'IDENTIFICADOR'=>'17',	'STRING'=>'',	'COMPARACAO'=>'',	'INTEIRO'=>'',	'REAL'=>'',		'SELECAO'=>'',	'PROJECAO'=>'',		'CARTESIANO'=>'',	'JUNCAO'=>'',	'UNIAO'=>'',	'AND'=>'',	'OR'=>'',	'NOT'=>''),
							'<PREDICADO2>'	=>array('$'=>'',	'('=>'18',	')'=>'',	'.'=>'',	','=>'',	'IDENTIFICADOR'=>'18',	'STRING'=>'',	'COMPARACAO'=>'',	'INTEIRO'=>'',	'REAL'=>'',		'SELECAO'=>'',	'PROJECAO'=>'',		'CARTESIANO'=>'',	'JUNCAO'=>'',	'UNIAO'=>'',	'AND'=>'',	'OR'=>'',	'NOT'=>''),
							'<PREDICADO3>'	=>array('$'=>'',	'('=>'',	')'=>'20',	'.'=>'',	','=>'',	'IDENTIFICADOR'=>'',	'STRING'=>'',	'COMPARACAO'=>'',	'INTEIRO'=>'',	'REAL'=>'',		'SELECAO'=>'',	'PROJECAO'=>'',		'CARTESIANO'=>'',	'JUNCAO'=>'',	'UNIAO'=>'',	'AND'=>'19','OR'=>'19',	'NOT'=>'19'),
							'<CRITERIO>'	=>array('$'=>'',	'('=>'',	')'=>'',	'.'=>'',	','=>'',	'IDENTIFICADOR'=>'21',	'STRING'=>'',	'COMPARACAO'=>'',	'INTEIRO'=>'',	'REAL'=>'',		'SELECAO'=>'',	'PROJECAO'=>'',		'CARTESIANO'=>'',	'JUNCAO'=>'',	'UNIAO'=>'',	'AND'=>'',	'OR'=>'',	'NOT'=>''),
							'<CRITERIO1>'	=>array('$'=>'',	'('=>'',	')'=>'',	'.'=>'',	','=>'',	'IDENTIFICADOR'=>'22',	'STRING'=>'23',	'COMPARACAO'=>'',	'INTEIRO'=>'24','REAL'=>'24',	'SELECAO'=>'',	'PROJECAO'=>'',		'CARTESIANO'=>'',	'JUNCAO'=>'',	'UNIAO'=>'',	'AND'=>'',	'OR'=>'',	'NOT'=>''),
							'<TABELA>'		=>array('$'=>'',	'('=>'',	')'=>'',	'.'=>'',	','=>'',	'IDENTIFICADOR'=>'25',	'STRING'=>'',	'COMPARACAO'=>'',	'INTEIRO'=>'',	'REAL'=>'',		'SELECAO'=>'',	'PROJECAO'=>'',		'CARTESIANO'=>'',	'JUNCAO'=>'',	'UNIAO'=>'',	'AND'=>'',	'OR'=>'',	'NOT'=>''),
							'<TABELA1>'		=>array('$'=>'27',	'('=>'27',	')'=>'27',	'.'=>'26',	','=>'27',	'IDENTIFICADOR'=>'',	'STRING'=>'',	'COMPARACAO'=>'27',	'INTEIRO'=>'',	'REAL'=>'',		'SELECAO'=>'',	'PROJECAO'=>'',		'CARTESIANO'=>'27',	'JUNCAO'=>'27',	'UNIAO'=>'27',	'AND'=>'27','OR'=>'27',	'NOT'=>'27'),
							'<ELEMENTO_I>'	=>array('$'=>'',	'('=>'',	')'=>'',	'.'=>'',	','=>'',	'IDENTIFICADOR'=>'28',	'STRING'=>'',	'COMPARACAO'=>'',	'INTEIRO'=>'',	'REAL'=>'',		'SELECAO'=>'',	'PROJECAO'=>'',		'CARTESIANO'=>'',	'JUNCAO'=>'',	'UNIAO'=>'',	'AND'=>'',	'OR'=>'',	'NOT'=>''),
							'<ELEMENTO_S>'	=>array('$'=>'',	'('=>'',	')'=>'',	'.'=>'',	','=>'',	'IDENTIFICADOR'=>'',	'STRING'=>'29',	'COMPARACAO'=>'',	'INTEIRO'=>'',	'REAL'=>'',		'SELECAO'=>'',	'PROJECAO'=>'',		'CARTESIANO'=>'',	'JUNCAO'=>'',	'UNIAO'=>'',	'AND'=>'',	'OR'=>'',	'NOT'=>''),
							'<ELEMENTO_N>'	=>array('$'=>'',	'('=>'',	')'=>'',	'.'=>'',	','=>'',	'IDENTIFICADOR'=>'',	'STRING'=>'',	'COMPARACAO'=>'',	'INTEIRO'=>'30','REAL'=>'31',	'SELECAO'=>'',	'PROJECAO'=>'',		'CARTESIANO'=>'',	'JUNCAO'=>'',	'UNIAO'=>'',	'AND'=>'',	'OR'=>'',	'NOT'=>''),
							'<ELEMENTO_L>'	=>array('$'=>'',	'('=>'',	')'=>'',	'.'=>'',	','=>'',	'IDENTIFICADOR'=>'',	'STRING'=>'',	'COMPARACAO'=>'',	'INTEIRO'=>'',	'REAL'=>'',		'SELECAO'=>'',	'PROJECAO'=>'',		'CARTESIANO'=>'',	'JUNCAO'=>'',	'UNIAO'=>'',	'AND'=>'32','OR'=>'33',	'NOT'=>'34')
	);
	/**
	 * Vetor contendo as regras de produção da nossa linguagem
	 * @var Matriz[R][R] R-Regras de produção
	 */
	protected $regras = array(
							'0'		=>array('<SELECAO>'),
							'1'		=>array('<PROJECAO>'),
							'2'		=>array('<CONJUNTO>'),
							'3'		=>array('PROJECAO','<CAMPOS>','(','<PROJECAO1>',')'),
							'4'		=>array('<TABELA>'),
							'5'		=>array('<SELECAO>'),
							'6'		=>array('SELECAO','(','<CONJUNTO>',')','<PREDICADO>'),
							'7'		=>array('<TABELA>','<CONJUNTO1>'),
							'8'		=>array('JUNCAO','<TABELA>'),
							'9'		=>array('UNIAO','<TABELA>'),
							'10'	=>array('CARTESIANO','<TABELA>'),
							'11'	=>array('î'),
							'12'	=>array('<TABELA>','<CAMPOS1>'),
							'13'	=>array(',','<CAMPOS>'),
							'14'	=>array('î'),
							'15'	=>array('<PREDICADO1>'),
							'16'	=>array('(','<PREDICADO2>',')'),
							'17'	=>array('<CRITERIO>'),
							'18'	=>array('<PREDICADO>','<PREDICADO3>'),
							'19'	=>array('<ELEMENTO_L>','<PREDICADO>'),
							'20'	=>array('î'),
							'21'	=>array('<TABELA>','COMPARACAO','<CRITERIO1>'),
							'22'	=>array('<TABELA>'),
							'23'	=>array('<ELEMENTO_S>'),
							'24'	=>array('<ELEMENTO_N>'),
							'25'	=>array('<ELEMENTO_I>','<TABELA1>'),
							'26'	=>array('.','<ELEMENTO_I>'),
							'27'	=>array('î'),
							'28'	=>array('IDENTIFICADOR'),
							'29'	=>array('STRING'),
							'30'	=>array('INTEIRO'),
							'31'	=>array('REAL'),
							'32'	=>array('AND'),
							'33'	=>array('OR'),
							'34'	=>array('NOT'),
	);
	protected $regrasByName = array(
							'0'		=>'<COMANDO>',
							'1'		=>'<COMANDO>',
							'2'		=>'<COMANDO>',
							'3'		=>'<PROJECAO>',
							'4'		=>'<PROJECAO1>',
							'5'		=>'<PROJECAO1>',
							'6'		=>'<SELECAO>',
							'7'		=>'<CONJUNTO>',
							'8'		=>'<CONJUNTO1>',
							'9'		=>'<CONJUNTO1>',
							'10'	=>'<CONJUNTO1>',
							'11'	=>'<CONJUNTO1>',
							'12'	=>'<CAMPOS>',
							'13'	=>'<CAMPOS1>',
							'14'	=>'<CAMPOS1>',
							'15'	=>'<PREDICADO>',
							'16'	=>'<PREDICADO1>',
							'17'	=>'<PREDICADO1>',
							'18'	=>'<PREDICADO2>',
							'19'	=>'<PREDICADO3>',
							'20'	=>'<PREDICADO3>',
							'21'	=>'<CRITERIO>',
							'22'	=>'<CRITERIO1>',
							'23'	=>'<CRITERIO1>',
							'24'	=>'<CRITERIO1>',
							'25'	=>'<TABELA>',
							'26'	=>'<TABELA1>',
							'27'	=>'<TABELA1>',
							'28'	=>'<ELEMENTO_I>',
							'29'	=>'<ELEMENTO_S>',
							'30'	=>'<ELEMENTO_N>',
							'31'	=>'<ELEMENTO_N>',
							'32'	=>'<ELEMENTO_L>',
							'33'	=>'<ELEMENTO_L>',
							'34'	=>'<ELEMENTO_L>',
	);
	/**
	 * Vetor contendo as regras de tradução da nossa linguagem
	 * @var Matriz[R][R] R-Regras de tradução
	 */
	protected $traducao = array(
							'0'		=>array('<SELECAO>'),
							'1'		=>array('<PROJECAO>'),
							'2'		=>array('<CONJUNTO>'),
							'3'		=>array('SELECT','<CAMPOS>','FROM','<PROJECAO1>'),
							'4'		=>array('<TABELA>'),
							'5'		=>array('<SELECAO>'),
							'6'		=>array('SELECT','*', 'FROM','<CONJUNTO>','WHERE','<PREDICADO>'),
							'7'		=>array('<TABELA>','<CONJUNTO1>'),
							'8'		=>array('JUNCAO','<TABELA>'),
							'9'		=>array('UNIAO','<TABELA>'),
							'10'	=>array('CARTESIANO','<TABELA>'),
							'11'	=>array('î'),
							'12'	=>array('<TABELA>','<CAMPOS1>'),
							'13'	=>array(',','<CAMPOS>'),
							'14'	=>array('î'),
							'15'	=>array('<PREDICADO1>'),
							'16'	=>array('(','<PREDICADO2>',')'),
							'17'	=>array('<CRITERIO>'),
							'18'	=>array('<PREDICADO>','<PREDICADO3>'),
							'19'	=>array('<ELEMENTO_L>','<PREDICADO>'),
							'20'	=>array('î'),
							'21'	=>array('<TABELA>','COMPARACAO','<CRITERIO1>'),
							'22'	=>array('<TABELA>'),
							'23'	=>array('<ELEMENTO_S>'),
							'24'	=>array('<ELEMENTO_N>'),
							'25'	=>array('<ELEMENTO_I>','<TABELA1>'),
							'26'	=>array('.','<ELEMENTO_I>'),
							'27'	=>array('î'),
							'28'	=>array('IDENTIFICADOR'),
							'29'	=>array('STRING'),
							'30'	=>array('INTEIRO'),
							'31'	=>array('REAL'),
							'32'	=>array('AND'),
							'33'	=>array('OR'),
							'34'	=>array('NOT'),
	);
	/**
	 * Pilha de elementos sintaticos.
	 * @var Vetor[]
	 */
	protected $pilha = array();
	/**
	 * Vetor contendo os simbolos(tokens) de entrada passados pelo analizador lexico.
	 * @var Vetor[tokens]
	 */
	protected $entrada = array();
	/**
	 * Saida gerada pelo analizador sintatico.
	 * @var ???????
	 */
	protected $saida = array();

	protected $arvore = array();
	/**
	 * Posição do simbolo atual
	 * @var int
	 */
	protected $posicao = 0;
	
	public function __construct(){

	}
	
	/**
	 * Informa se ainda simbolos de entrada a ser analizados
	 * @return boolean
	 */
    protected function temEntrada(){
        return $this->posicao < count($this->entrada);
    }
	
    /**
     * Retorna o proximo simbolo de entrada
     * @return Char
     */
    /*
    protected function nextToken(){
        if ($this->temEntrada()){
        	$token = $this->entrada[$this->posicao++];
        	if(is_object($token)){
        		return $token->getId();
        	}else{
        		return $token;
        	}
        }else{
            return '-1';
        }
    }
    */
	protected function nextToken(){
        if ($this->temEntrada()){
        	$token = $this->entrada[$this->posicao++];
        	if(is_object($token)){
        		return $token;
        	}else{
        		$t = new Token(0,0);
        		$t->setId('$');
        		return $t;
        	}
        }else{
            return '-1';
        }
    }
    
    protected function retiraPilha(){
    	$elemento_retirado = array_pop($this->pilha);
    }
    protected function colocaPilha($producoes){
   		$producoes = array_reverse($producoes);
   		foreach ($producoes as $producao) {
   			if($producao!='î'){
   				$this->pilha[] = $producao;
   			}
   			
   		}
    }
    protected function getTopoPilha(){
    	return $this->pilha[count($this->pilha)-1];
    }
    
	protected function isEREG($er, $c){
    	$r = ereg($er, $c);
    	if($r==0){
    		return false;
    	}else{
    		return true;
    	}
    }

} // End Core_Sintatico